# 条件表达式求值
import re
from typing import Dict, Any, List


class ExpressionEvaluator:
    """表达式求值器"""

    def __init__(self):
        self.operators = {
            "&&": (2, lambda x, y: x and y),
            "||": (1, lambda x, y: x or y),
            "!": (3, lambda x: not x),
        }

    def tokenize(self, expression: str) -> List[str]:
        """将表达式分词"""
        tokens = []
        i = 0
        n = len(expression)

        while i < n:
            if expression[i].isspace():
                i += 1
            elif expression[i] in "()!":
                tokens.append(expression[i])
                i += 1
            elif expression[i : i + 2] in self.operators:
                tokens.append(expression[i : i + 2])
                i += 2
            else:
                # 标识符或数值
                j = i
                while j < n and (expression[j].isalnum() or expression[j] in "_-"):
                    j += 1
                tokens.append(expression[i:j])
                i = j

        return tokens

    def shunting_yard(self, tokens: List[str]) -> List[str]:
        """将中缀表达式转换为后缀表达式"""
        output = []
        stack = []

        for token in tokens:
            if token in self.operators:
                while (
                    stack
                    and stack[-1] != "("
                    and (
                        self.operators[stack[-1]][0] > self.operators[token][0]
                        or (
                            self.operators[stack[-1]][0] == self.operators[token][0]
                            and token != "!"
                        )
                    )
                ):
                    output.append(stack.pop())
                stack.append(token)
            elif token == "(":
                stack.append(token)
            elif token == ")":
                while stack and stack[-1] != "(":
                    output.append(stack.pop())
                stack.pop()  # 移除 '('
            else:
                output.append(token)

        while stack:
            output.append(stack.pop())

        return output

    def evaluate_postfix(
        self, postfix: List[str], config_values: Dict[str, Any]
    ) -> bool:
        """计算后缀表达式"""
        stack = []

        for token in postfix:
            if token in self.operators:
                if token == "!":
                    if not stack:
                        return False
                    operand = stack.pop()
                    result = self.operators[token][1](operand)
                    stack.append(result)
                else:
                    if len(stack) < 2:
                        return False
                    b = stack.pop()
                    a = stack.pop()
                    result = self.operators[token][1](a, b)
                    stack.append(result)
            else:
                # 处理标识符或数值
                if token.lower() in ["y", "yes", "true", "1"]:
                    stack.append(True)
                elif token.lower() in ["n", "no", "false", "0"]:
                    stack.append(False)
                else:
                    # 从配置值中获取
                    value = config_values.get(token, False)
                    # 将值转换为布尔值
                    if isinstance(value, bool):
                        stack.append(value)
                    elif isinstance(value, str):
                        stack.append(value.lower() in ["y", "yes", "true", "1"])
                    elif isinstance(value, (int, float)):
                        stack.append(value != 0)
                    else:
                        stack.append(bool(value))

        return stack[0] if stack else False

    def evaluate(self, expression: str, config_values: Dict[str, Any]) -> bool:
        """计算表达式"""
        if not expression.strip():
            return True

        try:
            tokens = self.tokenize(expression)
            postfix = self.shunting_yard(tokens)
            return self.evaluate_postfix(postfix, config_values)
        except Exception as e:
            print(f"Error evaluating expression '{expression}': {e}")
            return False
